from pydantic import BaseModel, EmailStr, validator
from typing import Optional, List, Set, Dict, Any

class DepartmentBase(BaseModel):
    dept_name: str
    dept_id: str
    description: Optional[str] = None
    parent_id: Optional[str] = None
    order_num: Optional[int] = 0

class DepartmentCreate(DepartmentBase):
    pass

class DepartmentUpdate(BaseModel):
    dept_name: Optional[str] = None
    description: Optional[str] = None
    parent_id: Optional[str] = None
    order_num: Optional[int] = None

class DepartmentOut(BaseModel):
    id: int
    dept_id: str
    dept_name: str
    description: Optional[str] = None
    parent_id: Optional[str] = None
    parent_name: Optional[str] = None
    ancestors: Optional[str] = None
    level: int
    order_num: int
    created_at: Optional[str]
    updated_at: Optional[str]

class PermissionBase(BaseModel):
    name: str
    code: str
    description: Optional[str] = None

class PermissionCreate(PermissionBase):
    pass

class PermissionOut(PermissionBase):
    id: int
    created_at: Optional[str]
    updated_at: Optional[str]

class DepartmentPermissionAssign(BaseModel):
    """部门权限分配请求"""
    permission_ids: List[int]
    
class DepartmentWithPermissions(DepartmentOut):
    """带权限的部门信息"""
    permissions: Optional[List[PermissionOut]] = []

class DepartmentTreeNode(BaseModel):
    id: int
    dept_id: str
    dept_name: str
    description: Optional[str] = None
    parent_id: Optional[str] = None
    parent_name: Optional[str] = None
    ancestors: Optional[str] = None
    level: int
    order_num: int
    created_at: str
    updated_at: str
    children: Optional[List['DepartmentTreeNode']] = []

class DepartmentList(BaseModel):
    items: List[DepartmentOut]
    total: int

class DepartmentTree(BaseModel):
    items: List[DepartmentTreeNode]

class RoleBase(BaseModel):
    name: str
    code: str
    description: Optional[str] = None

class RoleCreate(RoleBase):
    permission_ids: Optional[List[int]] = []
    department_id: Optional[str] = None

class RoleUpdate(BaseModel):
    name: Optional[str] = None
    code: Optional[str] = None
    description: Optional[str] = None
    permission_ids: Optional[List[int]] = None
    department_id: Optional[str] = None

class RoleOut(RoleBase):
    id: int
    permissions: Optional[List[PermissionOut]] = []
    department_id: Optional[str] = None
    created_at: Optional[str]
    updated_at: Optional[str]

class RoleList(BaseModel):
    items: List[RoleOut]
    total: int

class UserCreate(BaseModel):
    username: str
    password: str
    email: EmailStr
    name: Optional[str] = None
    role_ids: Optional[List[int]] = []
    department_id: Optional[str] = None
    status: Optional[str] = "启用"

class UserLogin(BaseModel):
    username: str
    password: str

class UserOut(BaseModel):
    id: int
    username: str
    name: Optional[str] = None
    email: Optional[str] = None
    avatar: Optional[str] = None
    phone: Optional[str] = None
    gender: Optional[str] = None
    bio: Optional[str] = None
    roles: Optional[List[RoleOut]] = []
    department_id: Optional[str] = None
    department_name: Optional[str] = None
    department_path: Optional[str] = None
    status: Optional[str] = "启用"
    created_at: Optional[str]
    updated_at: Optional[str]

class UserUpdate(BaseModel):
    name: Optional[str] = None
    email: Optional[EmailStr] = None
    avatar: Optional[str] = None
    role_ids: Optional[List[int]] = None
    department_id: Optional[str] = None
    status: Optional[str] = None
    phone: Optional[str] = None
    gender: Optional[str] = None
    bio: Optional[str] = None

class UserPasswordChange(BaseModel):
    old_password: str
    new_password: str

class UserList(BaseModel):
    items: List[UserOut]
    total: int

class Token(BaseModel):
    access_token: str
    token_type: str

class TokenData(BaseModel):
    username: Optional[str] = None
    permissions: Optional[List[str]] = None

class PaginationParams(BaseModel):
    page: int = 1
    limit: int = 10

class PermissionList(BaseModel):
    items: List[PermissionOut]
    total: int 